﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Pex.Framework;
using Shweet.Repository.Moles;
using Shweet.Repository;

namespace Shweet.Engine.Tests
{
    [PexClass(typeof(Reader))]
    [TestClass]
    public partial class ReaderTests
    {
        [TestMethod]
        [HostType("Moles")]
        public void Read_NotFollowingAnyTeamsOneShweetOnCurrentSite_OneSheetReturned()
        {
            // Arrange
            var followedTeams = new List<Team>();
            var teams = new SITeams
                    {
                        GetAll = () => followedTeams
                    };

            var shweetMessage = new Repository.Shweet[] { new Repository.Shweet() { Text = "a" } };
            var shweetMessages = new SIShweetMessages
                     {
                         LoadStringArray = (tags) => shweetMessage
                     };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);

            // Assert
            Assert.AreEqual(1, actualShweets.Length);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_FollowingOneTeamWithOneShweetAndShweetInCurrentSite_TwoSheetsReturned()
        {
            // Arrange
            var followedTeams = new List<Team> {new Team() {Name = "a",Url="http://a", Following = true}};
            var shweetMessage = new Repository.Shweet[] { new Repository.Shweet() { Text = "a" } };
            
            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
            {
                LoadStringArray = (tags) => shweetMessage,
                LoadStringArrayString = (tags, siteUrl) => shweetMessage
            };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);
            // Assert
            Assert.AreEqual(2, actualShweets.Length);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_TwoTeamsEachWithOneShweet_TwoSheetsReturned()
        {
            // Arrange
            var followedTeams = new List<Team> { new Team() { Name = "a", Url = "http://a",Following = true}, new Team() {Name = "b", Url = "http://b",Following = true} };
            var shweetMessage = new Repository.Shweet[] { new Repository.Shweet() { Text = "a" } };

            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
            {
                LoadStringArray = (tags) => new Repository.Shweet[0],
                LoadStringArrayString = (tags, siteUrl) => shweetMessage // called for each team.
            };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);
            // Assert
            Assert.AreEqual(2, actualShweets.Length);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_TwoTeamsOneWithShweetNoShweetInCurrentSite_OneShweetReturned()
        {
            // Arrange
            bool firstTimeLoadCalled = true;
            var followedTeams = new List<Team> { new Team() { Following = true, Name = "a", Url = "http://a" }, new Team() {Following = true, Name = "b", Url = "http://b"} };
            var shweetMessage = new Repository.Shweet[] { new Repository.Shweet() { Text = "a" } };

            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
                 {
                     LoadStringArray = (tags) => new Repository.Shweet[0],
                     LoadStringArrayString = (tags, siteUrl) =>
                         {
                             if (firstTimeLoadCalled)
                             {
                                 firstTimeLoadCalled = false;
                                 return shweetMessage;
                             }
                             return new Repository.Shweet[0];
                         },
                 };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);
            // Assert
            Assert.AreEqual(1, actualShweets.Length);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_OneTeamWith20ShweetsAndCurrentSiteWith20Shweet_Return30Shweets()
        {
            // Arrange
            var followedTeams = new List<Team> { new Team() { Name = "a", Url = "http://a",Following = true}};
            var shweetMessage = new Repository.Shweet[20];

            for (int i = 0 ; i < 20 ;i++)
            {
                shweetMessage[i] = new Repository.Shweet {Text = "Message on : " + i};
            }

            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
            {
                LoadStringArray = (tags) => shweetMessage,
                LoadStringArrayString = (tags, siteUrl) => shweetMessage,
            };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);
            // Assert
            Assert.AreEqual(30, actualShweets.Length);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_ShweetsTwoTeams_ShweetsOrderedByShweetedOnDateDesc()
        {
            // Arrange
            var followedTeams = new List<Team> { new Team() { Name = "a", Url = "http://a",Following = true} };
            var shweetMessage = new Repository.Shweet[3];

            DateTime startDateForRandomDates = new DateTime(2010, 3, 1);

            for (int i = 0; i < 3; i++)
            {
                shweetMessage[i] = new Repository.Shweet {ShweetedOn = startDateForRandomDates.AddDays(i) };
            }

            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
            {
                LoadStringArray = (tags) => shweetMessage,
                LoadStringArrayString = (tags, siteUrl) => shweetMessage,
            };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);
            // Assert
            Assert.AreEqual(new DateTime(2010, 3, 3), actualShweets[0].ShweetedOn);
            Assert.AreEqual(new DateTime(2010, 3, 3), actualShweets[1].ShweetedOn);
            Assert.AreEqual(new DateTime(2010, 3, 2), actualShweets[2].ShweetedOn);
            Assert.AreEqual(new DateTime(2010, 3, 2), actualShweets[3].ShweetedOn);
            Assert.AreEqual(new DateTime(2010, 3, 1), actualShweets[4].ShweetedOn);
            Assert.AreEqual(new DateTime(2010, 3, 1), actualShweets[5].ShweetedOn);
        }

        [TestMethod]
        [HostType("Moles")]
        public void Read_TwoTeamsOneFollowingNoShweetsNotNoShweetsBothHaveAShweetInCurrentSite_OneShweetIsReturned()
        {
            // Arrange
            var followedTeams = new List<Team> { new Team() { Following = true, Url = "http://a"}, new Team() {Following = false, Url = "http://b"} };
            var shweetMessage = new Repository.Shweet[1] {new Repository.Shweet() {Text = "a"}};

            var teams = new SITeams
            {
                GetAll = () => followedTeams
            };

            var shweetMessages = new SIShweetMessages
            {
                LoadStringArray = (tags) => new Repository.Shweet[0],
                LoadStringArrayString = (tags, siteUrl) => shweetMessage,
            };

            // Act
            var reader = new Reader(shweetMessages, teams);
            Repository.Shweet[] actualShweets = reader.Read(new string[0]);

            // Assert
            Assert.AreEqual(1, actualShweets.Length);
        }

        [PexMethod]
        public void Read_LoadOnRepositoryGetCalledTheCorrectAmountOfTimes(int teamsFollowingCount)
        {
            PexAssume.IsTrue(teamsFollowingCount >= 0);

            List<Team> teams = new List<Team>();
            for (int i = 0; i < teamsFollowingCount;i++ )
            {
                Team team = new Team() {Following = true, Name = "a", Url = "http://a.com"};
                teams.Add(team);
            }

            // Arrange
            bool hasLoadBeenCalled = false;
            bool hasGetAllTeamBeenCalled = false;
            int totalCallsToLoad = 0;

            var fakeFollowers = new SITeams
                                    {
                                        GetAll = () =>
                                         {
                                             hasGetAllTeamBeenCalled = true;
                                             return teams;
                                         }
                                    };

            var fakeShweetMessages = new SIShweetMessages
                                         {
                                             LoadStringArray = (tags) =>
                                               {
                                                   totalCallsToLoad++;
                                                   hasLoadBeenCalled = true;
                                                   return new Repository.Shweet[0];
                                               },
                                            LoadStringArrayString = (tags, message) =>
                                           {
                                               totalCallsToLoad++;
                                               hasLoadBeenCalled = true;
                                               return new Repository.Shweet[0];
                                           }
                                     };

            // Act
            var reader = new Reader(fakeShweetMessages, fakeFollowers);
            reader.Read(new string[0]);
            
            // Assert
            Assert.IsTrue(hasLoadBeenCalled);
            Assert.IsTrue(hasGetAllTeamBeenCalled);
            Assert.AreEqual(teamsFollowingCount, totalCallsToLoad - 1);
        }
    }
}
